package cluster

import (
	"fmt"
	"github.com/emicklei/go-restful"
	"kubeInstall/install"
	"kubeInstall/pkg/logger"
	"kubeInstall/pkg/wsconn"
	"kubeInstall/server/models/app"
	modelCluster "kubeInstall/server/models/cluster"
	"kubeInstall/server/models/networkplugin"
	"kubeInstall/server/services/cluster"
	"kubeInstall/utils"
	"net/http"
	"time"
)

func AddInstallToRoute(ws *restful.WebService) {
	c := new(clusterHandler)
	ws.Route(ws.GET("/cluster/install/{cluster_id}").To(c.installCluster))
	logger.Info("add install cluster module successfully")
}

func (h *clusterHandler) installCluster(r *restful.Request, resp *restful.Response) {

	clusterId := r.PathParameter("cluster_id")

	if clusterId == "" {
		h.RenderError(resp, fmt.Sprintf("get cluster id from http query failed!"), http.StatusBadRequest)
		return
	}

	//获取集群配置
	clusterInfo, err := h.getClusterInfo(clusterId)

	if err != nil {
		h.RenderError(resp, fmt.Sprintf("get cluster failed! error is:  %v", err), http.StatusBadRequest)
		return
	}
	logger.Info("get cluster info success %+v", clusterInfo)
	s := wsconn.NewSession(resp, r.Request)
	s.HandleInComeMessage(func(bytes []byte) {

	})

	s.HandleOutputMessage(func(bytes []byte) {
		logger.Debug("sending msg: %s", string(bytes))
	})

	s.Run()

	ticker := time.NewTicker(30 * time.Minute)
	defer ticker.Stop()

	go h.install(clusterInfo)

	for {
		select {
		case data := <-utils.MsgQueue:
			err := s.Write(data)
			if err != nil {
				logger.Error("send msg to ws conn failed %v", err)
				s.CloseSession()
			}
		case <-ticker.C:
			logger.Error("install cluster time out")
			return
		}
	}

}

func (h *clusterHandler) install(clusterInfo *modelCluster.Cluster) error {
	logger.Info("start to install cluster!")
	//配置基础环境：docker，rpm包等等。
	for _, node := range clusterInfo.MasterNode {

		err := cluster.InitClusterBaseEnv(node, clusterInfo.HostNameMap)
		if err != nil {
			logger.Error("Init master node: %s BaseEnv failed", node.IP)
			return err
		}
	}

	for _, node := range clusterInfo.WorkerNode {
		err := cluster.InitClusterBaseEnv(node, clusterInfo.HostNameMap)
		if err != nil {
			logger.Error("Init worker node: %s BaseEnv failed", node.IP)
			return err
		}
	}

	//安装master0，初始化集群。
	logger.Info("start to init cluster master node")
	joinOpts, err := cluster.InitMaster0(clusterInfo)
	if err != nil {
		logger.Error(fmt.Sprintf("install cluster failed! error is:  %v", err))
		return err
	}

	if len(clusterInfo.MasterNode) > 1 {
		for _, m := range clusterInfo.MasterNode[1:] {
			logger.Info("start to join cluster master node: %s", m.IP)
			err = cluster.AddClusterMasterNode(m, joinOpts)
			if err != nil {
				logger.Error(fmt.Sprintf("add cluster master node :%v failed! error is:  %v", m, err))
				return err
			}
		}
	}

	//加入worker节点
	for _, w := range clusterInfo.WorkerNode {

		if clusterInfo.VipServer != "" {
			joinOpts.MasterIP = clusterInfo.VipServer + ":6443"
		}
		logger.Info("start to join cluster worker node: %s", w.IP)
		err = cluster.AddClusterWorkerNode(w, joinOpts)
		if err != nil {
			logger.Error(fmt.Sprintf("add cluster worker node :%v failed! error is:  %v", w, err))
			return err
		}
	}

	node0 := clusterInfo.MasterNode[0]
	sshOpt := install.NewSshOptions(node0)

	sshHandler, err := install.NewAsyncHandler(sshOpt)
	if err != nil {
		return err
	}

	logger.Info("start to add plugin for cluster!")
	//安装存储插件
	if clusterInfo.StorageType == "nfs" {

		for _, node := range clusterInfo.MasterNode {
			cluster.InstallNFS(node, clusterInfo.StoragePlugin.NFSServerIp,
				clusterInfo.StoragePlugin.NFSServerPath)
		}

		for _, node := range clusterInfo.WorkerNode {
			cluster.InstallNFS(node, clusterInfo.StoragePlugin.NFSServerIp,
				clusterInfo.StoragePlugin.NFSServerPath)
		}

		cluster.InstallApp(clusterInfo.StoragePlugin, sshHandler)

	}

	//安装网络插件
	calico := &networkplugin.NetworkPluginCalico{}
	cluster.InstallApp(calico, sshHandler)

	h.installPluginForCluster(clusterInfo, sshHandler)

	return nil
}

func (h *clusterHandler) installPluginForCluster(clusterInfo *modelCluster.Cluster, sshHandler *install.AsyncHandler) {
	// 安装node检查插件
	if clusterInfo.NodeProblemDetectorEnable {
		npd := &app.NPD{
		}

		cluster.InstallApp(npd, sshHandler)
	}

	// 安装DNS 缓存
	if clusterInfo.DnsCacheEnable {
		dnsIp := sshHandler.GetDNSServerIp()
		dns := &app.DnsCache{
			ClusterName: clusterInfo.ClusterName,
			LocalDNS:    "169.254.25.10",
			DNSServer:   dnsIp,
		}
		cluster.InstallApp(dns, sshHandler)
	}

	// 安装metric server 监控插件
	if clusterInfo.MetricServerEnable {
		metric := &app.MetricServer{
		}

		cluster.InstallApp(metric, sshHandler)
	}

	// 安装监控插件
	if clusterInfo.MonitorEnable {
		monitor := &app.Monitor{
		}

		cluster.InstallApp(monitor, sshHandler)

	}

	// 安装log server EFK
	if clusterInfo.LogEnable {
		log := &app.LogServer{}
		cluster.InstallApp(log, sshHandler)
	}

	// 安装ingress
	if clusterInfo.IngressEnable {
		ingress := &app.Ingress{
			IngressNodeName: clusterInfo.WorkerNode[0].HostName,
		}
		cluster.InstallApp(ingress, sshHandler)
		// 配置APP插件ingress
		ingressForApp := &app.IngressForAPP{
			DomainName:  clusterInfo.DomainName,
			ClusterName: clusterInfo.ClusterName,
		}

		cluster.InstallApp(ingressForApp, sshHandler)
	}

}
